package com.lianxi.stream;

import cn.hutool.core.util.ReUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.Test;

import javax.naming.Name;
import javax.xml.transform.Source;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class HelloStream {

    public static void main(String[] args) {
//        test1();

    }


    public static void test1() {
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("小昭");
        list.add("殷离");
        list.add("张三");
        list.add("张三丰");

        //寻找首字母为 张的
        list.stream().filter(name -> name.startsWith("张")).forEach(name -> System.out.println(name));
    }

    @Test
    public void test2() {
        List<String> list = Arrays.asList("a", "b", "c");
        Stream<String> stream = list.stream(); //顺序流
        Stream<String> stringStream = list.parallelStream();//并行流

        stream.forEach(s -> System.out.println("顺序流：" + s));
        stream.forEach(System.out::println);
        stringStream.forEach(s -> System.out.println("并行流：" + s));
    }

    @Test
    public void test3() {
        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
        //从0开始，依次加3，取前四个数    -----》 0,3,6,9
        Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
        stream2.forEach(System.out::println);
        Stream<Double> stream3 = Stream.generate(Math::random).limit(3);
        stream3.forEach(System.out::println);

    }

    @Test
    public void test4() {
        List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
        //大于6的依次打印
        list.stream().filter(s -> s > 6).forEach(System.out::println);

        //查找第一个大于6的数字
        Optional<Integer> findFirst = list.stream().filter(s -> s > 6).findFirst();

        // 匹配任意（适用于并行流）
        Optional<Integer> findAny = list.parallelStream().filter(x -> x > 6).findAny();

        // 是否包含符合特定条件的元素
        boolean anyMatch = list.stream().anyMatch(x -> x > 6);
        System.out.println("匹配第一个值：" + findFirst.get());
        System.out.println("匹配任意一个值：" + findAny.get());
        System.out.println("是否存在大于6的值：" + anyMatch);
    }


    /**
     * 筛选员工中工资高于8000的人的姓名，并形成新的集合。 形成新集合依赖collect（收集）
     */
    @Test
    public void test5() {
        List<Person> personList = new ArrayList<Person>();
        personList.add(new Person("Tom", 8900, 23, "male", "New York"));
        personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
        personList.add(new Person("Lily", 7800, 21, "female", "Washington"));
        personList.add(new Person("Anni", 8200, 24, "female", "New York"));
        personList.add(new Person("Owen", 9500, 25, "male", "New York"));
        personList.add(new Person("Alisa", 7900, 26, "female", "New York"));
        personList.parallelStream().filter(person -> person.getSalary() > 8000).collect(Collectors.toList()).forEach(System.out::println);
        personList.parallelStream().filter(person -> person.getSalary() > 8000).collect(Collectors.toList()).forEach(s -> System.out.println(s.getName()));
    }


    /**
     * 聚合（max、min、count）
     */
    @Test
    public void test6() {
        // 获取String集合中最长的元素(如果是顺序流,只返回第一个长度最长的字符串)
        List<String> l1 = Arrays.asList("adnm", "admmt", "pot", "xbangd", "weoujgsd");
        String s = l1.stream().max(Comparator.comparing(String::length)).get();
        System.out.println(s);


        // *********获取Integer集合中的最大值。
        List<Integer> l2 = Arrays.asList(7, 6, 9, 4, 11, 6);
        //自然排序
        Integer integer = l2.stream().max(Integer::compareTo).get();
        // 自定义排序
        Optional<Integer> max2 = l2.stream().max(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        });
        System.out.println(integer);


        //**********获取员工工资最高的人
        List<Person> personList = new ArrayList<Person>();
        personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
        personList.add(new Person("Tom", 8900, 23, "male", "New York"));
        personList.add(new Person("Lily", 7800, 21, "female", "Washington"));
        personList.add(new Person("Anni", 8200, 24, "female", "New York"));
        personList.add(new Person("Owen", 9500, 25, "male", "New York"));
        personList.add(new Person("Alisa", 7900, 26, "female", "New York"));
        Person person = personList.stream().max(Comparator.comparingInt(Person::getSalary)).get();
        System.out.println(person);

        //计算Integer集合中大于6的元素的个数。
        List<Integer> list = Arrays.asList(7, 6, 4, 8, 2, 11, 9);
        long count = list.stream().filter(n -> n > 6).count();
        System.out.println(count);

        //收集集合对象的某个属性的值
        personList.stream().map(person1 -> person1.getName()).collect(Collectors.toList()).stream().max(Comparator.comparingInt(String::length));

        //转换map
        personList.stream().collect(Collectors.toMap(Person::getName,person1->person1));



    }


    /**
     * 映射（map、flatMap）
     */
    @Test
    public void test7() {
        String[] strArr = {"abcd", "bcdd", "defde", "fTr"};
        List<String> strList = Arrays.stream(strArr).map(String::toUpperCase).collect(Collectors.toList());
        List<Integer> intList = Arrays.asList(1, 3, 5, 7, 9, 11);
        List<Integer> intListNew = intList.stream().map(x -> x + 3).collect(Collectors.toList());
        System.out.println("每个元素大写：" + strList);
        System.out.println("每个元素+3：" + intListNew);


        System.out.println("*****************");
        List<String> collect = Arrays.asList(strArr).stream().map(String::toUpperCase).collect(Collectors.toList());
        System.out.println(collect);

    }

    /**
     * 将员工的薪资全部增加1000。(map)
     */
    @Test
    public void test8() {
        List<Person> personList = new ArrayList<Person>();
        personList.add(new Person("Tom", 8900, 23, "male", "New York"));
        personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
        personList.add(new Person("Lily", 7800, 21, "female", "Washington"));
        personList.add(new Person("Anni", 8200, 24, "female", "New York"));
        personList.add(new Person("Owen", 9500, 25, "male", "New York"));
        personList.add(new Person("Alisa", 7900, 26, "female", "New York"));

        //将员工的薪资全部增加1000
        List<Person> collect = personList.stream().map(person -> {
            person.setSalary(person.getSalary() + 1000);
            return person;

        }).collect(Collectors.toList());
        System.out.println(collect);
    }


    @Test
    public void test9() {
        List<Integer> list = Arrays.asList(1, 6, 3, 4, 6, 7, 9, 6, 20);
        List<Integer> listNew = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());
        Set<Integer> set = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toSet());

        List<Person> personList = new ArrayList<Person>();
        personList.add(new Person("Tom", 8900, 23, "male", "New York"));
        personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
        personList.add(new Person("Lily", 7800, 21, "female", "Washington"));
        personList.add(new Person("Anni", 8200, 24, "female", "New York"));

        Map<?, Person> map = personList.stream().filter(p -> p.getSalary() > 8000)
                .collect(Collectors.toMap(Person::getName, p -> p));

        System.out.println("toList:" + listNew);
        System.out.println("toSet:" + set);
        System.out.println("toMap:" + map);
    }

}

@Data
@NoArgsConstructor
class Person {
    private String name;  // 姓名
    private int salary; // 薪资
    private int age; // 年龄
    private String sex; //性别
    private String area;  // 地区


    // 构造方法
    public Person(String name, int salary, int age, String sex, String area) {
        this.name = name;
        this.salary = salary;
        this.age = age;
        this.sex = sex;
        this.area = area;
    }
    // 省略了get和set，请自行添加

}


@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
class Employee {

    public static void main(String[] args) {

        List<Employee> employeeList = new ArrayList<>();
        employeeList.add(Employee.builder().name("Matt").salary(5000).office("New York").build());
        employeeList.add(Employee.builder().name("Steve").salary(6000).office("London").build());
        employeeList.add(Employee.builder().name("Carrie").salary(20000).office("New York").build());
        employeeList.add(Employee.builder().name("Peter").salary(7000).office("New York").build());
        employeeList.add(Employee.builder().name("Pat").salary(8000).office("London").build());
        employeeList.add(Employee.builder().name("Tammy").salary(29000).office("Shanghai").build());
        //找出工资最高
        employeeList.stream().max(Comparator.comparingInt(Employee::getSalary)).get();

        //查找办公室地点是New York的员工
        Optional<Employee> allMatchedEmployees = employeeList.stream().filter(employee -> employee.getOffice().equals("New York")).findAny();
        System.out.println(allMatchedEmployees);

        //按照工资的升序来列出员工信息
        List<Employee> sortEmployeeList = employeeList.stream().sorted(Comparator.comparingInt(Employee::getSalary)).collect(Collectors.toList());
        sortEmployeeList.forEach(employee -> System.out.println(employee.getSalary()));

        System.out.println("******************");

        //按照工资的降序来列出员工信息
        List<Employee> collect = employeeList.stream().sorted((x, y) -> Integer.compare(y.getSalary(), x.getSalary())).collect(Collectors.toList());
        collect.forEach(employee -> System.out.println(employee.getSalary()));

        System.out.println("按照工资的降序来列出员工信息（集合翻转）");
        //按照工资的降序来列出员工信息（集合翻转）
        List<Employee> c2 = employeeList.stream().sorted(Comparator.comparingInt(Employee::getSalary).reversed()).collect(Collectors.toList());
        c2.forEach(employee -> System.out.println(employee.getSalary()));

        List<Integer> collect1 = employeeList.stream().map(employee -> employee.getSalary()).collect(Collectors.toList());

        System.out.println("***分组操作***");
        //java8 分组操作
        Map<String, List<Employee>> groupMap = employeeList.stream().collect(Collectors.groupingBy(c -> c.getOffice()));

        groupMap.forEach((k, v) -> {
            if (k.equals("New York")) {
                List<Employee> collect2 = v.parallelStream().filter(employee -> employee.getSalary() >= 20000).collect(Collectors.toList());
                System.out.println(collect2);
            }
        });
    }
    private String name;
    private int salary;
    private String office;
}


@Data
@Builder
class User {
    private String name;
    private int id;
    private String city;
    private String sex;
    private LocalDateTime birthDay;


    public static void main(String[] args) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // data list
        List<User> userList = Arrays.asList(
                User.builder().id(123456).name("Zhang, San").city("ShangHai").sex("man").birthDay(LocalDateTime.parse("2022-07-01 12:00:00", df)).build(),
                User.builder().id(777777).name("Zhang, San").city("ShangHai").sex("woman").birthDay(LocalDateTime.parse("2022-07-01 12:00:00", df)).build(),
                User.builder().id(888888).name("Li, Si").city("ShangHai").sex("man").birthDay(LocalDateTime.parse("2022-07-01 12:00:00", df)).build(),
                User.builder().id(999999).name("Zhan, San").city("HangZhou").sex("woman").birthDay(LocalDateTime.parse("2022-07-01 12:00:00", df)).build(),
                User.builder().id(555555).name("Li, Si").city("NaJin").sex("man").birthDay(LocalDateTime.parse("2022-07-01 12:00:00", df)).build()
        );
        Map<String, List<User>> groupMap = userList.stream()
                .collect(Collectors.groupingBy(User::getCity));
        groupMap.forEach((k, v) -> {
            System.out.println(k);
            System.out.println(v);
        });
    }
}
